<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Add a stretchable image to the map</title>
    <meta
      name="viewport"
      content="initial-scale=1,maximum-scale=1,user-scalable=no"
    />
    <script src="../../lib/mapbox-gl.js"></script>
    <link href="../../lib/mapbox-gl.css" rel="stylesheet" />
    <script src="../../lib/axios.min.js"></script>
    <style>
      body {
        margin: 0;
        padding: 0;
      }
      #map {
        position: absolute;
        top: 0;
        bottom: 0;
        width: 100%;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>
    <script>
      let baseDataUrl = `http://${localStorage.getItem(
        "host"
      )}/mapbox-gl-js-offline-examples`;
      axios
        .get(
          baseDataUrl +
            `/resources/styles/${localStorage.getItem(
              "mbtilesStylesName"
            )}.json`
        )
        .then((res) => {
          let data = res.data;
          initMap(data);
        })
        .catch((err) => {
          console.error(err);
        });

      function initMap(style) {
        let map = new mapboxgl.Map({
          container: "map",
          center: [121.163, 31.161],
          zoom: 0.1,
          style: style,
        });

        var images = {
          popup: baseDataUrl + "/data/images/icon/popup.png",
          "popup-debug": baseDataUrl + "/data/images/icon/popup_debug.png",
        };

        loadImages(images, function (loadedImages) {
          map.on("load", function () {
            map.addImage("popup-debug", loadedImages["popup-debug"], {
              // The two (blue) columns of pixels that can be stretched horizontally:
              //   - the pixels between x: 25 and x: 55 can be stretched
              //   - the pixels between x: 85 and x: 115 can be stretched.
              stretchX: [
                [25, 55],
                [85, 115],
              ],
              // The one (red) row of pixels that can be stretched vertically:
              //   - the pixels between y: 25 and y: 100 can be stretched
              stretchY: [[25, 100]],
              // This part of the image that can contain text ([x1, y1, x2, y2]):
              content: [25, 25, 115, 100],
              // This is a high-dpi image:
              pixelRatio: 2,
            });
            map.addImage("popup", loadedImages["popup"], {
              stretchX: [
                [25, 55],
                [85, 115],
              ],
              stretchY: [[25, 100]],
              content: [25, 25, 115, 100],
              pixelRatio: 2,
            });

            map.addSource("points", {
              type: "geojson",
              data: {
                type: "FeatureCollection",
                features: [
                  {
                    type: "Feature",
                    geometry: {
                      type: "Point",
                      coordinates: [40, -30],
                    },
                    properties: {
                      "image-name": "popup-debug",
                      name: "Line 1\nLine 2\nLine 3",
                    },
                  },
                  {
                    type: "Feature",
                    geometry: {
                      type: "Point",
                      coordinates: [40, 30],
                    },
                    properties: {
                      "image-name": "popup",
                      name: "Line 1\nLine 2\nLine 3",
                    },
                  },
                  {
                    type: "Feature",
                    geometry: {
                      type: "Point",
                      coordinates: [-40, -30],
                    },
                    properties: {
                      "image-name": "popup-debug",
                      name: "One longer line",
                    },
                  },
                  {
                    type: "Feature",
                    geometry: {
                      type: "Point",
                      coordinates: [-40, 30],
                    },
                    properties: {
                      "image-name": "popup",
                      name: "One longer line",
                    },
                  },
                ],
              },
            });
            map.addLayer({
              id: "points",
              type: "symbol",
              source: "points",
              layout: {
                "text-field": ["get", "name"],
                "icon-text-fit": "both",
                "icon-image": ["get", "image-name"],
                "icon-allow-overlap": true,
                "text-allow-overlap": true,
                "text-font": ["Open Sans Regular"],
              },
            });

            // the original, unstretched image for comparison
            map.addSource("original", {
              type: "geojson",
              data: {
                type: "FeatureCollection",
                features: [
                  {
                    type: "Feature",
                    geometry: {
                      type: "Point",
                      coordinates: [0, -70],
                    },
                  },
                ],
              },
            });
            map.addLayer({
              id: "original",
              type: "symbol",
              source: "original",
              layout: {
                "text-field": "unstretched image",
                "icon-image": "popup-debug",
                "icon-allow-overlap": true,
                "text-allow-overlap": true,
                "text-font": ["Open Sans Regular"],
              },
            });
          });
        });

        function loadImages(urls, callback) {
          var results = {};
          for (var name in urls) {
            map.loadImage(urls[name], makeCallback(name));
          }

          function makeCallback(name) {
            return function (err, image) {
              results[name] = err ? null : image;

              // if all images are loaded, call the callback
              if (Object.keys(results).length === Object.keys(urls).length) {
                callback(results);
              }
            };
          }
        }
      }
    </script>
  </body>
</html>
